<!--
  Author: 善良的YWJ
  Created by shanliangdeYWJ on 2020/09/09
  File: 05.3解决异步设置值每个组件都是独立的.html
  Description: "
  
   请输入文件描述内容
  
               " 
  Github: https://github.com/shanliangdeYWJ
-->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
  <meta name="keywords" content="">
  <meta name="description" content="">
  <title>05.3每个组件都是独立的</title>
  <style></style>
</head>

<body>
  <!-- 这是 react渲染到页面上的结点 可以创建多个节点 -->
  <div id="root"></div>

  <!-- 加载 React。-->
  <!-- 注意: 部署时，将 "development.js" 替换为 "production.min.js"。-->
  <script src="../js/react@16.development.js" crossorigin></script>
  <script src="../js/react-dom@16.development.js" crossorigin></script>
  <script src="../js/babel@6.min.js"></script>


  <!-- 加载我们的 React 组件。-->
  <script type="text/babel">

    // ### 将函数组件转换成 class 组件
    /**
     * @class Clock
     * 封装一个 Clock 组件
     * 只要在相同的 DOM 节点中渲染 <Clock /> ，
     * 就仅有一个 Clock 组件的 class 实例被创建使用。
     * 
     * 当 Clock 组件第一次被渲染到 DOM 中的时候，就为其设置一个计时器。这在 React 中被称为“挂载（mount）”。
     * 同时，当 DOM 中 Clock 组件被删除的时候，应该清除计时器。这在 React 中被称为“卸载（unmount）”。
     * 为 class 组件声明一些特殊的方法，当组件挂载或卸载时就会去执行这些方法：
     * 
     * @typedef {{date:Date}} ClockProps
     * @extends {React.Component<ClockProps>}
     */
    class Clock extends React.Component {

      constructor(props) {
        super(props)
        /** 
         * 1. 不要直接修改 State, 
         * 2. 应该使用 setState() 
         * 3. State 的更新可能是异步的 （出于性能考虑，React 可能会把多个 setState() 调用合并成一个调用。不要依赖他们的值来更新下一个状态。）
         *  - 要解决这个问题，可以让 setState() 接收一个函数而不是一个对象。
         *  - 箭头函数 普通函数都可以
         *    - this.setState((state, props) => ({ counter: state.counter + props.increment }));
         *    - this.setState(function(state, props) { return { counter: state.counter + props.increment }; });
         */
        this.state = { date: new Date() }
        this.timerID = null
      }
      /** 组件已经被渲染到 DOM 中后运行，所以，最好在这里设置计时器 */
      componentDidMount() {
        this.timerID = setInterval(
          () => this.tick(),
          1000
        )
      }

      componentWillUnMount() {
        clearInterval(this.timerID);
      }

      tick() {
        this.setState({
          date: new Date()
        })
      }

      render() {
        const { date, num } = this.props
        return (
          <div>
            <h1>This is Clock {num}!</h1>
            <h2>It's {this.state.date.toLocaleTimeString()}.</h2>
          </div >
        );
      }
    }

    function App() {
      return (
        <div>
          <p> 每个 Clock 组件都会单独设置它自己的计时器并且更新它。</p>
          <Clock num={1} />
          <Clock num={2} />
          <Clock num={3} />
        </div>
      )
    }

    ReactDOM.render(
      <App />,
      document.getElementById('root')
    );
  </script>
</body>

</html>